/*
 * cartography.cpp
 *
 *  Created on: 08.04.2012
 *      Author: ignacio
 */


#include "cartography.h"
#include <ClanLib/Display/2D/color.h>
#include "clanlib.h"
#include <iostream>
using std::cout;
using std::endl;
#include <cmath>
using std::pow;
#include <sstream>
using std::ostringstream;
#include <iomanip>

#include <algorithm>
using std::find;
using std::max;
using std::min;
#include "Graph.h"

namespace neurignacio
{
BinaryMask::BinaryMask(buffer_t& buffer)
{
	typedef CL_Colorf pixel_t;
	width=buffer.get_width();
	height=buffer.get_height();
	array = new data_t* [height];
	for (register size_t y=0; y<height; ++y)
	{
		array[y] = new data_t [width];
		for (register size_t x=0; x<width; ++x)
		{
			pixel_t pixel;
			pixel=buffer.get_pixel(x,y);
			array[y][x] = static_cast<data_t>( (pixel.get_red() + pixel.get_blue() + pixel.get_green()) * (pow(256,sizeof(data_t))-1) / 3 );	// Get rid of color info and stores in 8-bit grayscale
		}
	}
}

BinaryMask::BinaryMask(const size_t& w, const size_t& h, const data_t& background) : width(w), height(h)
{
	array = new data_t* [height];
	for (register size_t y=0; y<height; ++y)
	{
		array[y] = new data_t [width];
		for (register size_t x=0; x<width; ++x)
		{
			array[y][x] = background;
		}
	}
}

BinaryMask::BinaryMask(const BinaryMask& img) : width(img.width), height(img.height)
{
	array = new data_t* [height];
	for (register size_t y=0; y<height; ++y)
	{
		array[y] = new data_t [width];
		for (register size_t x=0; x<width; ++x)
		{
			array[y][x] = img.array[y][x];
		}
	}
}

BinaryMask& BinaryMask::operator=(const BinaryMask& img)
{
	if (this!= &img)	// Protect against self-assignment
	{
		for (register size_t y=0; y<height; ++y)
			for (register size_t x=0; x<width; ++x)
				array[y][x] = img.array[y][x];
	}
	return *this;
}

BinaryMask::~BinaryMask()
{
	for (register size_t y=0; y<height; ++y)
		delete [] array[y];
	delete [] array;
}

inline BinaryMask::data_t BinaryMask::get_pixel(const size_t& x, const size_t& y) const
{
	if (x>=0 && x < width && y>=0 && y << height)
		return (*this)(x,y);
	else	// Out of range Error!
		return -1;
}

inline void BinaryMask::set_pixel(const size_t& x, const size_t& y, data_t& value)
{
		if (x>=0 && x < width && y>=0 && y << height)
			(*this)(x,y)=value;
		else	// Out of range Error!
			return;
}

BinaryMask::buffer_t BinaryMask::getBuffer()
{
	buffer_t buffer(width, height, CL_TextureFormat::cl_rgba8);
	unsigned int *data= buffer.get_data_uint32();
	for (size_t y=0; y<height; ++y)
		for (size_t x=0; x<width; ++x)
		{
			unsigned char red = (*this)(x,y);
			unsigned char green = (*this)(x,y);
			unsigned char blue = (*this)(x,y);
			unsigned char alpha = 255;
			data[x+y*width] = (red << 24) + (green << 16) + (blue << 8) + alpha;
		}

	return buffer;
}

inline CircularArray::size_t CircularArray::getIndex(const int& i) const
{
	int index=i;	// I use CONST int& i
	if (index<0)
		index = (this->size()-((-index) % this->size()));

	return (index % this->size());
}

inline CircularArray::data_t& CircularArray::index(const int& i)
{
//	cout << "Line " << __LINE__ << " Index: " << getIndex(i) << endl;
	return container_t::operator[](getIndex(i));
}

inline CircularArray::data_t CircularArray::index(const int& i) const
{
//	cout << "Line " << __LINE__ << " Index: " << getIndex(i) << endl;
	return container_t::operator[](getIndex(i));
}

StructuringElement::StructuringElement(const size_t& size) : center(), ring(size-1)
{
//	cout << "Created ring of size " << ring.size() << endl;
}

PixelWindow::PixelWindow(BinaryMask* img, const size_t& x0, const size_t& y0) : StructuringElement(9), image(img), x(x0), y(y0)
{
//	cout << "PixelWindow::PixelWindow("<<(int)x<<","<<(int)y<<")"<< endl;
	if (x>0 && y>0 && x<img->getWidth()-1 && y<img->getHeight()-1)
		this->setCenter(x,y);
}

void PixelWindow::setCenter(const size_t& x0, const size_t& y0)
{
	x=x0;
	y=y0;
//	cout << "PixelWindow::setCenter(" << (int)x << ", " << (int)y << ")" << endl;
	// 0 is the upper left corner and goes clockwise.
	// 0 1 2
	// 7 X 3
	// 6 5 4
	(*this)()=(*image)(x,y);
	(*this)[0]=(*image)(x-1,y-1);
	(*this)[1]=(*image)(x,y-1);
	(*this)[2]=(*image)(x+1,y-1);
	(*this)[3]=(*image)(x+1,y);
	(*this)[4]=(*image)(x+1,y+1);
	(*this)[5]=(*image)(x,y+1);
	(*this)[6]=(*image)(x-1,y+1);
	(*this)[7]=(*image)(x-1,y);
}

Vector3 PixelWindow::pixel(const int& i)
{
	data_t index = this->ring.getIndex(i);
	signed char deltaX=0;
	if (index>=2 && index<=4)
		deltaX = 1;
	else if (index>=6 || index==0)
		deltaX = -1;
	signed char deltaY=0;
	if (index<=2)
		deltaY=-1;
	else if (index>=4 && index<=6)
		deltaY = 1;
	Vector3 p(x+deltaX, y+deltaY);
	return p;
}

int PixelWindow::findPixel(const size_t& x0, const size_t& y0)
{
	int pos;
	// 1. Check if (x,y) is the center
	if (x0==x && y0==y)
		pos=-1;
	else if (x0-x==-1 && y0-y==-1)
		pos=0;
	else if (x0-x==0 && y0-y==-1)
		pos=1;
	else if (x0-x==1 && y0-y==-1)
		pos=2;
	else if (x0-x==1 && y0-y==0)
		pos=3;
	else if (x0-x==1 && y0-y==1)
		pos=4;
	else if (x0-x==0 && y0-y==1)
		pos=5;
	else if (x0-x==-1 && y0-y==1)
		pos=6;
	else if (x0-x==-1 && y0-y==0)
		pos=7;
	else	// Not in PixelWindow
		pos=8;
	return pos;
}

ostream& operator<<(ostream& out, const StructuringElement& element)
//	7 0 1
//	6 C 2
//	5 4 3
{
	cout << (int)element.ring[7] << " " << (int)element.ring[0] << " " << (int)element.ring[1] << endl;
	cout << (int)element.ring[6] << " " << (int)element.center << " " << (int)element.ring[2] << endl;
	cout << (int)element.ring[5] << " " << (int)element.ring[4] << " " << (int)element.ring[3] << endl;
}

void BinaryMask::binarize(const data_t& threshold, const data_t& foreground, const data_t& background)
{
	for (register size_t y=0; y<height; ++y)
		for (register size_t x=0; x<width; ++x)
		{
			if ((*this)(x,y)>=threshold)
				(*this)(x,y)=foreground;
			else
				(*this)(x,y)=background;
		}
}

void BinaryMask::skeletonize(const data_t& foreground)
// Own Implementation based on paper
{
	data_t background = !foreground;
	BinaryMask newImage(width, height, background);	// Create New Image filled with background
//	cout << "********** Skeletonize (foreground="<< (int)foreground << ", background=" << (int)background << ")" << endl;
	unsigned int count;
	unsigned int loop =1;
	do
	{
		count = 0;
		// First Iteration
		for (register size_t y=1; y<height-1; ++y)
			for (register size_t x=1; x<width-1; ++x)
			{
				// Check if center pixel is foreground
				if ((*this)(x,y)==foreground)
				{
//					cout << "(" << x << "," << y << ")=" << (int)(*this)(x,y) << endl;
					// 0. Assigments
					// 	  Clock-Wise Order starting from 12 o'clock
					StructuringElement st(9);
					st()=(*this)(x,y);
					st[0]=(*this)(x,y-1);
					st[1]=(*this)(x+1,y-1);
					st[2]=(*this)(x+1,y);
					st[3]=(*this)(x+1,y+1);
					st[4]=(*this)(x,y+1);
					st[5]=(*this)(x-1,y+1);
					st[6]=(*this)(x-1,y);
					st[7]=(*this)(x-1,y-1);
//					cout << st << endl;
					// 1. Total number of pattern |0|1| is equal to 1
					unsigned int patternTotal=0;
					// 2. Number of foreground pixels is between 4 and 7, both inclusive
					unsigned int foregroundTotal=0;
					for (register size_t i=0; i<st.ringSize(); ++i)
					{
						// Calculate 1.
						if (st[i]!=foreground && st[i+1]==foreground)
							++patternTotal;
						// Calculate 2.
						if (st[i]==foreground)
							++foregroundTotal;
					}
					// 3. Calculate right T
					bool rightT=  (st[0]== foreground && st[2]==foreground && st[4] == foreground);
					// 4. Calculate bottom T
					bool bottomT=  (st[0]== foreground && st[2]==foreground && st[4] == foreground);
					// Check conditions
					// Zhang Suen's Paper: foregroundTotal=[2,7]
					// Blog: foregroundTotal=[4,7]
					// Nice: foregroundTotal=[2,6]
//					cout << "patternTotal: "<< patternTotal << " foregroundTotal: " << foregroundTotal << " rightT: " << rightT << " bottomT: "<< bottomT << endl;
					if (patternTotal==1 && foregroundTotal>=2 && foregroundTotal <=6 && rightT == 0 && bottomT == 0)
					{
						newImage(x,y) = background;
						++count;
//						cout << "(" << x << "," << y << ") marked for deletion!" << endl;
						//cout << "(" << x << "," << y << ")=" << (int)(*this)(x,y) << endl;
						//cout << st << endl;
					} // end if conditions for deletion
					else
						newImage(x,y) = foreground;
				} // end if center pixel is foreground
				else
					newImage(x,y)=background;	//
			}// end First Iteration


		// If count is zero, terminate
		if (!count)
		{
//			cout << "Count is " << count << " in Line " << __LINE__ << "... BREAK!" << endl;
			break;
		}
/*		std::ostringstream oss1;
		oss1 << "./Resources/path01_skeleton_";
		oss1 << std::setw( 3 ) << std::setfill( '0' ) << loop;
		oss1 << ".png";
		CL_PixelBuffer png_copy1=newImage.getBuffer();
//		cout << "loop="<< loop << " count=" << count << " save to " << oss.str() << " (Line" << __LINE__ << ") " << endl;
		CL_PNGProvider::save(png_copy1, oss1.str());
		++loop;
*/

		// Second Iteration
		count = 0;
		for (register size_t y=1; y<height-1; ++y)
			for (register size_t x=1; x<width-1; ++x)
			{
				// Check if center pixel is foreground
				if (newImage(x,y)==foreground)
				{
					// 0. Assigments
					// 	  Clock-Wise Order starting from 12 o'clock
					StructuringElement st(9);
					st()=newImage(x,y);
					st[0]=newImage(x,y-1);
					st[1]=newImage(x+1,y-1);
					st[2]=newImage(x+1,y);
					st[3]=newImage(x+1,y+1);
					st[4]=newImage(x,y+1);
					st[5]=newImage(x-1,y+1);
					st[6]=newImage(x-1,y);
					st[7]=newImage(x-1,y-1);
					// 1. Total number of pattern |0|1| is equal to 1
					unsigned int patternTotal=0;
					// 2. Number of foreground pixels is between 5 and 7, both inclusive
					unsigned int foregroundTotal=0;
					for (register size_t i=0; i<st.ringSize(); ++i)
					{
						// Calculate 1.
						if (st[i]!=foreground && st[i+1]==foreground)
							++patternTotal;
						// Calculate 2.
						if (st[i]==foreground)
							++foregroundTotal;
					}

					// 3. Calculate top T
					bool topT = (st[0]== foreground && st[2]==foreground && st[6] == foreground);
					// 4. Calculate left T
					bool leftT = (st[0]== foreground && st[4]==foreground && st[6] == foreground);
					// Check conditions
					// Zhang Suen's Paper: foregroundTotal=[2,7]
					// Blog: foregroundTotal=[5,7]
					// Nice: foregroundTotal=[2,6]
					if (patternTotal==1 && foregroundTotal>=2 && foregroundTotal <=6 && topT == 0 && leftT == 0)
					{
						(*this)(x,y) = background;
						++count;
					}
					else
						(*this)(x,y) = foreground;
				} // end if center pixel is foreground
				else
					(*this)(x,y) = background;
			}// end Second Iteration
			// If count is zero, copy newImage to *this and terminate
			if (!count)
			{
//				cout << "Count is " << count << " in Line " << __LINE__ << "... BREAK!" << endl;
				*this=newImage;
//				break;
			}

//*this=newImage;
/*			std::ostringstream oss;
			oss << "./Resources/path01_skeleton_";
			oss << std::setw( 3 ) << std::setfill( '0' ) << loop;
			oss << ".png";
			CL_PixelBuffer png_copy=getBuffer();
			cout << "loop="<< loop << " count=" << count << " save to " << oss.str() << " (Line" << __LINE__ << ") " << endl;
			CL_PNGProvider::save(png_copy, oss.str());
			++loop;
*/
//count = 0;
	} // end while
	while (count);
}

void BinaryMask::skeletonize_ij(const BinaryMask::data_t& foreground)
/*  Modified from ImageJ (BinaryProcessor.java)
  	Uses a lookup table to repeatably removes pixels from the
	edges of objects in a binary image, reducing them to single
	pixel wide skeletons. Based on an a thinning algorithm by
	by Zhang and Suen (CACM, March 1984, 236-239). There is
	an entry in the table for each of the 256 possible 3x3 neighborhood
	configurations. An entry of '1' means delete pixel on first pass, '2' means
	delete pixel on second pass, and '3' means delete on either pass. A graphical
	representation of the 256 neighborhoods indexed by the table is available
	at "http://imagej.nih.gov/ij/images/skeletonize-table.gif".
*/
{
	int table[] =
			//0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1
			 {0,0,0,1,0,0,1,3,0,0,3,1,1,0,1,3,0,0,0,0,0,0,0,0,2,0,2,0,3,0,3,3,
			  0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,3,0,2,2,
			  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
			  2,0,0,0,0,0,0,0,2,0,0,0,2,0,0,0,3,0,0,0,0,0,0,0,3,0,0,0,3,0,2,0,
			  0,0,3,1,0,0,1,3,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
			  3,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
			  2,3,1,3,0,0,1,3,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
			  2,3,0,1,0,0,0,1,0,0,0,0,0,0,0,0,3,3,0,1,0,0,0,0,2,2,0,0,2,0,0,0};
	BinaryMask::data_t background = !foreground;
	BinaryMask newImage(width, height, background);	// Create New Image filled with background

	int count=100;
	int pixelsRemoved=0;
	do
	{
		// First Iteration
		pixelsRemoved = 0;
		for (register size_t y=1; y<height-1; ++y)
			for (register size_t x=1; x<width-1; ++x)
			{
				newImage(x,y)=(*this)(x,y);
				if ((*this)(x,y)==foreground)
					{
					// 0. Assigments
					// 	  Clock-Wise Order starting from 12 o'clock
					StructuringElement st(9);
					st()=(*this)(x,y);
					st[0]=(*this)(x-1,y-1);
					st[1]=(*this)(x,y-1);
					st[2]=(*this)(x+1,y-1);
					st[3]=(*this)(x+1,y);
					st[4]=(*this)(x+1,y+1);
					st[5]=(*this)(x,y+1);
					st[6]=(*this)(x-1,y+1);
					st[7]=(*this)(x-1,y);

					int index = 0;
					for (register size_t i=0; i<st.ringSize(); ++i)
					{
						if (st[i]==foreground) index |= ( 1 << i); // 1 << i = 2^i
					}
					int code = table[index];
					if (code==1 || code == 3)
						{
							newImage(x,y)=background;
							++pixelsRemoved;
						}
					} // end if foreground
			} // end for x
		// Second Iteration
		pixelsRemoved = 0;
		for (register size_t y=1; y<height-1; ++y)
			for (register size_t x=1; x<width-1; ++x)
			{
				(*this)(x,y)=newImage(x,y);
				// Check if center pixel is foreground
				if (newImage(x,y)==foreground)
				{
					// 0. Assigments
					// 	  Clock-Wise Order starting from 12 o'clock
					StructuringElement st(9);
					st()=newImage(x,y);
					st[0]=newImage(x-1,y-1);
					st[1]=newImage(x,y-1);
					st[2]=newImage(x+1,y-1);
					st[3]=newImage(x+1,y);
					st[4]=newImage(x+1,y+1);
					st[5]=newImage(x,y+1);
					st[6]=newImage(x-1,y+1);
					st[7]=newImage(x-1,y);

					int index = 0;
					for (register size_t i=0; i<st.ringSize(); ++i)
					{
						if (st[i]==foreground) index |= ( 1 << i); // 1 << i = 2^i
					}
					int code = table[index];
					if (code==2 || code == 3)
						{
							(*this)(x,y)=background;
							++pixelsRemoved;
						} // end if code
				} // end if foreground
			} // end for
	} // end do-while
	while (pixelsRemoved>0);
}

BinaryMask::VectorList BinaryMask::intersections(const BinaryMask::data_t& foreground)
{
/*
	To find intersection points is fairly obvious. Just scan with a
	window looking for a pattern in the 9 pixels that indicates a
	crossing. For example, the middle pixel is 1 and at least three of
	the 8 neighbor pixels are also 1 provided that they have a zero in
	between
	http://www.mathworks.com/matlabcentral/newsreader/view_thread/308698
 */
	VectorList intersections;
	for (register size_t y=1; y<height-1; ++y)
		for (register size_t x=1; x<width-1; ++x)
		{
			if ((*this)(x,y)==foreground)
				{
				// 0. Assigments
				// 	  Clock-Wise Order starting from 12 o'clock
				StructuringElement st(9);
				st()=(*this)(x,y);
				st[0]=(*this)(x-1,y-1);
				st[1]=(*this)(x,y-1);
				st[2]=(*this)(x+1,y-1);
				st[3]=(*this)(x+1,y);
				st[4]=(*this)(x+1,y+1);
				st[5]=(*this)(x,y+1);
				st[6]=(*this)(x-1,y+1);
				st[7]=(*this)(x-1,y);

				unsigned char foregroundPixels=0;
				for (register size_t i=0; i<st.ringSize(); ++i)
					{
						if (st[i]==foreground && st[i+1]!=foreground) // look for patterns '10'
						{
							++foregroundPixels;
						}
					} // end 'st' loop
				if (foregroundPixels>=3)
					// This is an intersection
					{
//						cout << "(" << x << ", " << y << ")" << " is an intersection" << endl;
						Vector3 pixel(x,y);
						intersections.push_back(pixel);
					} // end foregroundPixels>=3
				} // end if foreground
		}
	return intersections;
}

Hypergraph<Vector3> BinaryMask::connections(VectorList& intersections, const BinaryMask::data_t& foreground)
// Types of Connections:
// 	Intersection <-> Endpoint
//  Intersection <-> Corner
//  Intersection <-> Intersection
//  	  Corner <-> Corner
//		  Corner <-> Endpoint
//		Endpoint <-> Endpoint (only if no intersections)
{
	Hypergraph<Vector3> G;
	Vector3 u;
	Vector3 v;
	VectorList dummyEndPointList;
	VectorList dummyIntersectionList;
	VectorList dummyCornerList;
	for (VectorList::iterator intersection=intersections.begin(); intersection!=intersections.end(); ++intersection)
	{
		// I will add the intersection to the Graph as a milestone (therefore corners around intersection won't be added)
		G.addVertex(*intersection);
	}

	for (VectorList::iterator intersection=intersections.begin(); intersection!=intersections.end(); ++intersection)
	{
		const real DIST_MAX=2; // distance under which two points are considered to be the same
		cout << "Intersection (" << intersection->x << ", " << intersection->y << ") XXXXXXXXXXXXXXXXXXXXXXxx" << endl;
		// A. Make the 'u' vertex of the connection
		// 1. Place Window in pixel
		PixelWindow st(this, intersection->x, intersection->y);
		// 2. Find the roots (branching points) of this intersection
		VectorList branchingPoints;
//		cout << "\tbranchingPoints:";
//		cout << st;
		for (register size_t i=0; i<st.ringSize(); ++i)
		{
			if (st[i]==foreground) // look for foreground pixels
			{
				Vector3 p=st.pixel(i);
				branchingPoints.push_back(p);
//				cout << " (" << p.x << ", " << p.y << ")="<<(int)(*this)(p.x,p.y) << "["<<(int)st[i]<<"]";
			}
		} // end 'st' loop
//		cout << endl;
		// 3. Follow each of the branches till I find a pixel included to the intersection list or an endpoint
		//	  Initial conditions: Window is in one of the roots, 'previousPixel' is the intersection point.
		for (VectorList::iterator branch = branchingPoints.begin(); branch!=branchingPoints.end(); ++branch)
		{
			cout << "\tBranching Point: " << *branch << "++++++++++++++++++++++++++++++" << endl;
			// 1. Initial Conditions
			u = *intersection; // Initially the 'u' node is the intersection point.
			Vector3 previousPixel(intersection->x, intersection->y);
			int iPrevious=-1000;	// Minus Infinite means no initialized
			int iNext=1000;			// Plus Infinite means no initialized
			Vector3 nextPixel=previousPixel;
//			cout << "Branch point: " << *branch << " previous pixel: " << previousPixel << endl;
			PixelWindow st(this, branch->x, branch->y);
			// 2. Check window's ring for foreground pixels
			bool isIntersection=false;
			bool isEndPoint=false;
			bool BREAK = false;
			// From here, move the window till we find an intersection or an end point
			do
			{
			int foregroundCount=0;
			for (register unsigned i=0; i<st.ringSize(); ++i)
				{
					if (st[i]==foreground)
					{
						// a. Is the foreground pixel an intersection?
						// find st.pixel(i) in intersections VectorList
						// if yes, then we finished
//						cout << "Checking " << st.pixel(i) << " Line (" << __LINE__ << ")" << endl;
						if (find(intersections.begin(), intersections.end(), st.pixel(i)) == intersections.end())
						{
//							cout << st.pixel(i) << " is not an intersection" << endl;
							// if not found, is the foreground pixel the previous Pixel?
							// st.pixel(i)==previousPixel
							if (st.pixel(i)!=previousPixel)
							{
//								cout << st.pixel(i) << " is not the previous pixel" << endl;
								// if not previousPixel, is the foreground pixel one of the branching points?
								// find st.pixel(i) in roots VectorList
								++foregroundCount; // we are not in an end point.
								if (find(branchingPoints.begin(), branchingPoints.end(), st.pixel(i)) == branchingPoints.end())
								{
									// if not, this is the candidate pixel I should go!!!!
//									cout << st.pixel(i) << " is not a branching point" << endl;

									//previousPixel = st.centerPixel();
									iNext=i;
									nextPixel=st.pixel(i);
//									cout << "Found Candidate in st["<<i<<"]=" << nextPixel << endl;
									//++i;
									// however, I will continue checking the rest of foreground pixels, in case I find a new intersection on them
									//continue;
									//st.setCenter(nextPixel);
//									cout << "Going to next pixel " << nextPixel << "(Line "<< __LINE__ << ")" << endl;
									//break;

								} // st.pixel(i) is not a root
								else
								{
//									cout << st.pixel(i) << "is a branching point, therefore I continue" << endl;
									// this pixel is one of the branching point from the current intersection, so just go to the next pixel of the window's ring
									continue;
								}
							} // st.pixel(i) is not the previous pixel
							else
							{
//								cout << st.pixel(i) << "is the previous pixel, therefore I continue" << endl;
								// this pixel is the one that i came from, so just go to the next pixel of the window's ring
								continue;
							}
						} // st.pixel(i) is not a intersection
						else
						{
//							cout << st.pixel(i) << " is an intersection, therefore I check if I'm the actual intersection" << endl;
							if (st.pixel(i)!=*intersection)
							{
								// We found the next intersection point
								isIntersection = true;
								cout << "\t\tFound intersection" << st.pixel(i) << "(Line "<< __LINE__ << ") ################################################" << endl;
								// make an edge from actual intersection to this intersection point
								// go the the next branch
// I have to add u=(intersection or corner) to v=st.pixel(i)
								dummyIntersectionList.push_back(st.pixel(i));
								// Here is the intersection point, connect it to 'u' and viceversa. 'u' should be updated at the beginning of the loop
								// Intersection is a unique point and it should be added to the graph even if it's close to other points.
								//VectorVertex* vPointer = G.getPointer(st.pixel(i),DIST_MAX);
								//if (!vPointer) // 'v' is not in the Graph
								//{
									v = st.pixel(i);
									cout << "\t\t*Adding Intersection Edge from " << u << " to " << v << endl;
									G.addEdge(u,v);
									G.addEdge(v,u);
								//}
								//
								// Create forward Edge(pixel, st.centerPixel());
								// Create reverse Edge(pixel, st.centerPixel())
								// if forward Edge is not in the adjacencyList of the actual intersection, add it
								// if reverse Edge is not in the adjacencyList of the discovered intersection point, add it. (optional)
								//
								break;
							}
							else
							{
//								cout << st.pixel(i) << "is the actual intersection, therefore I continue" << endl;
								continue;
							}
						}

					} // st[i] == foreground
					else
					{
						// Do nothing, just go to the next pixel of the window's ring
						continue;
					}
					// This is the pixel where I should go (nextPixel), I will check first if it's in same line or it's a corner point
					// for that i need to know where in the ring is the previous pixel (iPrevious) and the pixel I should go (iNext)
					// if max(iNext, Previous) = min(iPrevious,iNext) + 4, then iPrevious, center of the window and i are in the same line, otherwise center of the window is a corner.
					if (iPrevious>0 && max(iPrevious,iNext)!=min(iPrevious,iNext)+4)
					{
						// Corner Pixel
						cout << "\t\tCorner Found: " << previousPixel << " (iPrevious="<< iPrevious << ")~" << st.centerPixel() << "~" << nextPixel << " (iNext=" << iNext << ") => " << max(iPrevious,iNext)-min(iPrevious,iNext) << endl;
						dummyCornerList.push_back(st.centerPixel());
						// This is the corner, so I connect 'u' to it and assign 'u' to be now this corner.
						// Corner is a secondary point and it shouldn't be added to the graph if it's close to other points.
						VectorVertex* vPointer = G.getPointer(st.centerPixel(),DIST_MAX);
						if (!vPointer) // 'v' is not in the Graph
						{
							v = st.centerPixel();
							cout << "\t\t*Adding Corner Edge from " << u << " to " << v;
							G.addEdge(u, v);
							G.addEdge(v, u);
							u = st.centerPixel();
							cout << " ('u' is updated to  " << u << ")" << endl;
						}
						else  // there is 'v' near the corner, I rather add it to here
						{
							cout << "\t\t- I found another vertex here: " << *vPointer << " so I will connect u=" << u << " to this one (it will be probably connected somewhere at the end)" << endl;
							if (*(vPointer->value) == previousPixel)
							{
								cout << "\t\t :*) It's the previous pixel, so I will continue like if nothing happened" << endl;
							}
							else // end if v is the previous pixel
							{
								v = *(vPointer->value);
								if (u!=v)
								{
									cout << "\t\t* Adding Extra Edge from " << u << " to " << v;
									G.addEdge(u, v);
									G.addEdge(v, u);
								}
								else
								{
									cout << "\t\t% Wait a second! u=" << u << " and v=" << v << " are the same point! Then there is nothing to do!" << endl;
								}
								BREAK = true;
								break; // 'v' will be probably connected somewhere at the end
							} // end else (v is not the previous pixel)
						}
					}
					// Now go the the next pixel
					// first, assign the center of the actual window as the previous pixel
					// then move the window to the next pixel
					// lastly, find the index of the previous window in the new window
					previousPixel = st.centerPixel();
					st.setCenter(nextPixel);
					iPrevious=st.findPixel(previousPixel);
					cout << "I was in " << previousPixel << " and I go now to next pixel " << nextPixel << "(Line "<< __LINE__ << ")" << endl;
				} // end for st.ringSize *************************************************************************************************************************************
			// if we didn't find any pixel to continue
			if (!foregroundCount)
			{
				// we are in an end point.
				 isEndPoint = true;
				 cout << "\t\tFound end point" << st.centerPixel() << "[foregroundCount="<<foregroundCount<<"] " << "(Line "<< __LINE__ << ") **************************************************" << endl;
				 dummyEndPointList.push_back(st.centerPixel());
				// Create and Edge from the actual intersection to the discovered end point
				// add it to the adjacency List of the actual intersection

				// This is a End Point, simply connect 'u' to it. 'u' should be update at the beginning of the loop.
				// Endpoint is a unique point and it should be added to the graph even if it's close to other points?
				VectorVertex* vPointer = G.getPointer(st.centerPixel(),DIST_MAX);
				if (!vPointer) // 'v' is not in the Graph
				{
					 v = st.centerPixel();
					 cout << "\t\t*Adding EndPoint Edge from " << u << " to " << v << endl;
					 G.addEdge(u, v);
					 G.addEdge(v, u);
				}
				break;
			}

			// 2. Check for the next point in the branch

			} // end for i in st.ringSize()
			while (!isEndPoint && !isIntersection && !BREAK);

		} // end for all branches

	} // end for all pixels in intersections
/*	cout << "END POINT LIST: " << endl;
	for (VectorList::iterator endpoint=dummyEndPointList.begin(); endpoint!=dummyEndPointList.end(); ++endpoint)
		cout << *endpoint << endl;
	cout << "INTERSECTION LIST: " << endl;
	for (VectorList::iterator intersection=dummyIntersectionList.begin(); intersection!=dummyIntersectionList.end(); ++intersection)
		cout << *intersection << endl;
	cout << "CORNER LIST: " << endl;
	for (VectorList::iterator corner=dummyCornerList.begin(); corner!=dummyCornerList.end(); ++corner)
		cout << *corner << endl;
*/
	/*
	 * endpoints and corner points are redundant, need to eliminate those that are that are repeated and those that are intersection points.
	 */
	return G;
}

void cartography_example()
{
/*	CL_PixelBuffer png_image = CL_PNGProvider::load("./Resources/maze01.png");
	BinaryMask mask(png_image);
	cout << "Making Binary" << endl;
	mask.binarize(255,255,0);
//	CL_PixelBuffer png_copy1=mask.getBuffer();
//	CL_PNGProvider::save(png_copy1, "./Resources/path01_skeleton_000.png");
	cout << "Skeletonize" << endl;
	mask.skeletonize_ij(255);
//	CL_PixelBuffer png_copy2=mask.getBuffer();
//	CL_PNGProvider::save(png_copy2, "./Resources/path01_skeleton.png");


*/	CL_PixelBuffer png_image = CL_PNGProvider::load("./Resources/maze01_skeleton.png");
	BinaryMask mask(png_image);
	cout << "Searching Intersections" << endl;
	BinaryMask::VectorList intersections=mask.intersections(255);
	cout << "Finding Connections" << endl;
	Hypergraph<Vector3> G=mask.connections(intersections,255);
	cout << "Graph Connections: size=" << G.size() << endl;
//	for (Hypergraph<Vector3>::iterator it=G.begin(); it!=G.end(); ++it)
//		cout << *(it->first) << endl;
	cout << G;
	Vector3 startPoint(30,29);
	Vector3 endPoint(485, 476);
	cout << "A_Star:"<< endl;
	G.A_Star(startPoint,endPoint);
	G.PrintPath(startPoint,endPoint);
	// Export Path to Clanlib
	Path<VectorVertex> vertexPath=G.getPath(startPoint,endPoint);
	VectorPath path=VertexPathToVectorPath(vertexPath);
	cout << "DONE." << endl;
}



} // end namespace neurignacio

